#include <vector>
#include "mapDM.h"
#include "tmapParser.h"
#include <iostream>
using namespace std;


//--------------------------------------------------------

Mapping_C::Mapping_C(parser_C* p_pParser)
{
     p_pParser->getGate(m_vgate);
}

//-------------------------------------------------------

void Mapping_C::test(int zz)
{
     //int zz=2;
     cout<<"gate name= "<<m_vgate[zz]->name<<"  "<<"id= "<<m_vgate[zz]->id<<endl;
     cout<<"output=  ";
     for(unsigned int i=0;i<m_vgate[zz]->output.size();++i)
     {
           cout<<m_vgate[zz]->output[i]->name<<"  "<<m_vgate[zz]->output[i]->id<<"  ";
     }
     cout<<endl<<"input=  ";
     for(unsigned int i=0;i<m_vgate[zz]->input.size();++i)
     {
           cout<<m_vgate[zz]->input[i]->name<<"  "<<m_vgate[zz]->input[i]->id<<"  ";
     }
     cout<<endl<<endl;

}

//------------------------------------------------------


void Mapping_C::converttoAIG()
{
     int length=m_vgate.size();
     int lastgate=length-1;
     for(int iter=0;iter<length;++iter)
     {
           if(m_vgate[iter]->getid()==3)//nand
           {
                 m_vgate.push_back(new Gate("and",1));
                 m_vgate.push_back(new Gate("not",0));
                 setconnection(m_vgate[lastgate+1],m_vgate[lastgate+2]);
                 m_vgate[lastgate+1]->input=m_vgate[iter]->input;
                 m_vgate[lastgate+2]->output=m_vgate[iter]->output;
                 fixoutput(m_vgate[lastgate+1],m_vgate[iter]);
                 fixinput(m_vgate[lastgate+2],m_vgate[iter]);
                 
                 m_vgate.erase(m_vgate.begin()+iter);
                 lastgate+=1;
           }

           else if(m_vgate[iter]->getid()==4)//or
           {
                 m_vgate.push_back(new Gate("not",0));
                 m_vgate.push_back(new Gate("not",0));
                 m_vgate.push_back(new Gate("and",1));
                 m_vgate.push_back(new Gate("not",0));
                 setconnection(m_vgate[lastgate+1],m_vgate[lastgate+3]);
                 setconnection(m_vgate[lastgate+2],m_vgate[lastgate+3]);
                 setconnection(m_vgate[lastgate+3],m_vgate[lastgate+4]);
                 m_vgate[lastgate+1]->setinput(m_vgate[iter]->input[0]);
                 m_vgate[lastgate+2]->setinput(m_vgate[iter]->input[1]);
                 m_vgate[lastgate+4]->output=m_vgate[iter]->output;
                 fixoutput(m_vgate[lastgate+1],m_vgate[iter]);
                 fixoutput(m_vgate[lastgate+2],m_vgate[iter]);
                 fixinput(m_vgate[lastgate+4],m_vgate[iter]);
                 m_vgate.erase(m_vgate.begin()+iter);
                 lastgate+=3;
           }

           else if(m_vgate[iter]->getid()==5)//nor
           {
                 m_vgate.push_back(new Gate("not",0));
                 m_vgate.push_back(new Gate("not",0));
                 m_vgate.push_back(new Gate("and",1));
                 setconnection(m_vgate[lastgate+1],m_vgate[lastgate+3]);
                 setconnection(m_vgate[lastgate+2],m_vgate[lastgate+3]);
                 m_vgate[lastgate+1]->setinput(m_vgate[iter]->input[0]);
                 m_vgate[lastgate+2]->setinput(m_vgate[iter]->input[1]);
                 m_vgate[lastgate+3]->output=m_vgate[iter]->output;
                 fixoutput(m_vgate[lastgate+1],m_vgate[iter]);
                 fixoutput(m_vgate[lastgate+2],m_vgate[iter]);
                 fixinput(m_vgate[lastgate+3],m_vgate[iter]);
                 m_vgate.erase(m_vgate.begin()+iter);
                 lastgate+=2;
           }

           else if(m_vgate[iter]->getid()==6)//xor
           {
                 m_vgate.push_back(new Gate("not",0));
                 m_vgate.push_back(new Gate("and",1));
                 m_vgate.push_back(new Gate("not",0));
                 m_vgate.push_back(new Gate("and",1));
                 m_vgate.push_back(new Gate("not",0));
                 m_vgate.push_back(new Gate("not",0));
                 m_vgate.push_back(new Gate("and",1));
                 m_vgate.push_back(new Gate("not",0));
                 m_vgate.push_back(new Gate("buf",2));
                 m_vgate.push_back(new Gate("buf",2));
                 setconnection(m_vgate[lastgate+1],m_vgate[lastgate+2]);
                 setconnection(m_vgate[lastgate+3],m_vgate[lastgate+4]);
                 setconnection(m_vgate[lastgate+2],m_vgate[lastgate+5]);
                 setconnection(m_vgate[lastgate+4],m_vgate[lastgate+6]);
                 setconnection(m_vgate[lastgate+5],m_vgate[lastgate+7]);
                 setconnection(m_vgate[lastgate+6],m_vgate[lastgate+7]);
                 setconnection(m_vgate[lastgate+7],m_vgate[lastgate+8]);
                 setconnection(m_vgate[lastgate+9],m_vgate[lastgate+2]);
                 setconnection(m_vgate[lastgate+9],m_vgate[lastgate+3]);
                 setconnection(m_vgate[lastgate+10],m_vgate[lastgate+1]);
                 setconnection(m_vgate[lastgate+10],m_vgate[lastgate+4]);
                 m_vgate[lastgate+9]->setinput(m_vgate[iter]->input[0]);
                 m_vgate[lastgate+10]->setinput(m_vgate[iter]->input[1]);
                 m_vgate[lastgate+8]->output=m_vgate[iter]->output;
                 fixoutput(m_vgate[lastgate+9],m_vgate[iter]);
                 fixoutput(m_vgate[lastgate+10],m_vgate[iter]);
                 fixinput(m_vgate[lastgate+8],m_vgate[iter]);
                 m_vgate.erase(m_vgate.begin()+iter);
                 lastgate+=9;
           }

           else if(m_vgate[iter]->getid()==7)//xnor
           {
                 m_vgate.push_back(new Gate("not",0));
                 m_vgate.push_back(new Gate("and",1));
                 m_vgate.push_back(new Gate("not",0));
                 m_vgate.push_back(new Gate("and",1));
                 m_vgate.push_back(new Gate("not",0));
                 m_vgate.push_back(new Gate("not",0));
                 m_vgate.push_back(new Gate("and",1));
                 m_vgate.push_back(new Gate("buf",2));
                 m_vgate.push_back(new Gate("buf",2));
                 setconnection(m_vgate[lastgate+1],m_vgate[lastgate+2]);
                 setconnection(m_vgate[lastgate+3],m_vgate[lastgate+4]);
                 setconnection(m_vgate[lastgate+2],m_vgate[lastgate+5]);
                 setconnection(m_vgate[lastgate+4],m_vgate[lastgate+6]);
                 setconnection(m_vgate[lastgate+5],m_vgate[lastgate+7]);
                 setconnection(m_vgate[lastgate+6],m_vgate[lastgate+7]);
                 setconnection(m_vgate[lastgate+8],m_vgate[lastgate+2]);
                 setconnection(m_vgate[lastgate+8],m_vgate[lastgate+3]);
                 setconnection(m_vgate[lastgate+9],m_vgate[lastgate+1]);
                 setconnection(m_vgate[lastgate+9],m_vgate[lastgate+4]);
                 m_vgate[lastgate+8]->setinput(m_vgate[iter]->input[0]);
                 m_vgate[lastgate+9]->setinput(m_vgate[iter]->input[1]);
                 m_vgate[lastgate+7]->output=m_vgate[iter]->output;
                 fixoutput(m_vgate[lastgate+8],m_vgate[iter]);
                 fixoutput(m_vgate[lastgate+9],m_vgate[iter]);
                 fixinput(m_vgate[lastgate+7],m_vgate[iter]);
                 m_vgate.erase(m_vgate.begin()+iter);
                 lastgate+=8;
           }
     
     
     }

}

void Mapping_C::setconnection(Gate* source,Gate* target)
{
      source->setoutput(target);
      target->setinput(source);
}

void Mapping_C::fixoutput(Gate* ori,Gate* trash)//ori's input
{
     Gate* tar;
     for(unsigned int iter=0;iter<ori->input.size();++iter)
     {
           tar=ori->input[iter];
           for(unsigned int tariter=0;tariter<tar->output.size();++tariter)
           {
                 if(tar->output[tariter]==trash)
                 { 
                       tar->output[tariter]=ori;
                       break;
                 }
           }
     }
}


void Mapping_C::fixinput(Gate* ori,Gate* trash)//ori's output
{
     Gate* tar;
     for(unsigned int iter=0;iter<ori->output.size();++iter)
     {
           tar=ori->output[iter];
           for(unsigned int tariter=0;tariter<tar->input.size();++tariter)
           {
                 if(tar->input[tariter]==trash)
                 { 
                       tar->input[tariter]=ori;
                       break;
                 }
           }
     }
}

//----------------------------------------------------------------------







